package de.eventdroid.helper_classes;

import java.util.HashMap;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.net.Uri;
import android.os.Bundle;
import android.test.IsolatedContext;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;


public class GeoDataHandler {
	
	private Intent handleIntent = new Intent();
	private static final double ROUNDING_FACTOR = 1e6;
	private static final long LOCATION_UPDATE_MIN_TIME = 1000L;
	private static final float LOCATION_UPDATE_MIN_DISTANCE = 20.0f;
	protected static LocationManager actualLocationManager;
	protected static LocationListener actualGPSLocationListener;
	protected static LocationListener actualNetworkLocationListener;
	protected static double actual_latitude = 0.0;
	protected static double actual_longitude = 0.0;
	protected static Location actual_location;
	
	/* Test GPS Data for search and creation tests */
	private static Point essenHbf = new Point(51452242,7013737);
	private static Point essenCity = new Point(51456400,7011162);
	private static Point stolbergCity = new Point(50770360,6229505);
	private static Point duesseldorfHbf = new Point(51219653,6794221);
	
	/**
	 * This method prepares the Intent for a exchange of data for an external Application,
	 * which the User can choose after Android offered the possible Applications which can
	 * handle it.
	 * 
	 * @param intendedOperation The switching parameter for choosing which type of Intent is designated
	 * @param intentParameters The data Values which are necessary to fulfill the Intent
	 * @return The prepared Intent with for the calling Method
	 */
	@SuppressWarnings("all")
	public Intent createExternalDataExchange(String intendedOperation, HashMap intentParameters) {
		
		try {
			actual_latitude = (Double) intentParameters.get("latitude");
			actual_longitude = (Double) intentParameters.get("longitude");
		} catch (NumberFormatException nfe) {
			Log.e("Number Format Exception", " Thrown when parsing GEODATA in GeoDataHandler: "+nfe);			
		}
		
		if(intendedOperation.equals("google_maps")) {
			handleIntent = new Intent(Intent.ACTION_VIEW,
		    Uri.parse("geo:"+actual_latitude+","+actual_longitude+"?z=20"));
		}
		
		return handleIntent;
	}
	
	/**
	 * Gets the actual GPS position of the user from the GPS module included in the device
	 * @return the point within the actual GPS position
	 */		
	public static Point getActualGPSPosition(Activity actualActivity) {
		
		/* Indicate the locationManager for finding out the actual position */
		actualLocationManager = (LocationManager) actualActivity.getSystemService(Context.LOCATION_SERVICE);		
		
		/* Check criteria for finding our which provider is the best */
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
		String bestProvider = actualLocationManager.getBestProvider(criteria, true);
		
		/* The actual GPS-LocationListener */
		actualGPSLocationListener = new LocationListener() {
			
			public void onStatusChanged(String provider, int status, Bundle extras) {
				
				switch (status) {
	                case LocationProvider.AVAILABLE:
	                    Log.i("GPS-PROVIDER: Location Provider Available", "Location Provider Available");
	                    break;
	                case LocationProvider.OUT_OF_SERVICE:
	                	Log.i("GPS-PROVIDER: Location out of service", "Location out of service");
	                    break;
	                case LocationProvider.TEMPORARILY_UNAVAILABLE:
	                	Log.i("GPS-PROVIDER: Location temporary unavailable", "Location temporary unavailable");
	                    break;
	                    
				}
			
			}
			
			public void onProviderEnabled(String provider) {
			}
			
			public void onProviderDisabled(String provider) {
			}
			
			public void onLocationChanged(Location location) {
				actual_latitude = location.getLatitude();
				actual_longitude= location.getLongitude();				
			}
		};
		
		/* The actual Network-LocationListener */
		actualNetworkLocationListener = new LocationListener() {
			
			public void onStatusChanged(String provider, int status, Bundle extras) {
				
				switch (status) {
	                case LocationProvider.AVAILABLE:
	                    Log.i("NETWORK-PROVIDER: Location Provider Available", "Location Provider Available");
	                    break;
	                case LocationProvider.OUT_OF_SERVICE:
	                	Log.i("NETWORK-PROVIDER: Location out of service", "Location out of service");
	                    break;
	                case LocationProvider.TEMPORARILY_UNAVAILABLE:
	                	Log.i("NETWORK-PROVIDER: Location temporary unavailable", "Location temporary unavailable");
	                    break;
				}
				
			}
			
			public void onProviderEnabled(String provider) {
			}
			
			public void onProviderDisabled(String provider) {
			}
			
			public void onLocationChanged(Location location) {
				actual_latitude = location.getLatitude();
				actual_longitude= location.getLongitude();	
			}
		};
		
		/* Figure out which Provider is available and take one of it ORDER: 1st GPS-Provider / 2nd Network-Provider */
		if(actualLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
			actualLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, LOCATION_UPDATE_MIN_TIME, LOCATION_UPDATE_MIN_DISTANCE, actualGPSLocationListener);
			actual_location = actualLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		} else if(actualLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
			actualLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, LOCATION_UPDATE_MIN_TIME, LOCATION_UPDATE_MIN_DISTANCE, actualNetworkLocationListener);
			actual_location = actualLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
		}
		
		/* Get the current location based on the provider */ 
		if(actual_location != null && actual_location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
			actual_latitude = actual_location.getLatitude();
			actual_longitude = actual_location.getLongitude();
		} else if(actual_location != null && actual_location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {		
			actual_latitude = actual_location.getLatitude();
			actual_longitude = actual_location.getLongitude();
		}
		
		/* deactivate updates for location indication */
		actualLocationManager.removeUpdates(actualNetworkLocationListener);
		actualLocationManager.removeUpdates(actualGPSLocationListener);
		
		return new Point((int) (actual_latitude * ROUNDING_FACTOR), (int) (actual_longitude * ROUNDING_FACTOR));
	}
	
	/**
	 * This method indicates if even one Provider is enabled
	 * @param actualActivity the calling activity
	 * @return true if a supported provider is enabled, false if not
	 */
	public static boolean isProviderActive(Activity actualActivity) {
		
		actualLocationManager = (LocationManager) actualActivity.getSystemService(Context.LOCATION_SERVICE);	
		return (actualLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) 
				|| actualLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER));
		
	}
	
}

